
import os
import sys
import shutil
import platform
import subprocess
import time
import configparser
import logging
import hashlib
import traceback

COMMON_PATH = os.path.dirname(os.path.realpath(__file__))
CODE_PATH = os.path.dirname(COMMON_PATH)
ROOT_PATH = os.path.dirname(CODE_PATH)

logging.basicConfig(level=logging.INFO,
                format='%(asctime)s [%(filename)s-%(lineno)d-%(levelname)s] %(message)s',
                datefmt='%Y-%m-%d %H:%M:%S',
                )

def call(*args, **keywords):
    logging.info(args)
    ret, text = getstatusoutput(*args, **keywords)
    if ret != 0:
        logging.error(text)
        return False
    return True


def getstatusoutput(cmd, cwd=None, env=None, timeout=None):
    shell = True if isinstance(cmd, str) else False
    ret = subprocess.run(cmd, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cwd, env=env, timeout=timeout)
    try:
        text = ret.stdout.decode('UTF-8')
    except UnicodeDecodeError:
        text = ret.stdout.decode('gbk', errors='ignore')
    return ret.returncode, text
    
def myprint(pstr, leval="INFO"):
    now = time.strftime("%Y-%m-%d %H:%M:%S")
    line = sys._getframe().f_back.f_lineno
    back_file = sys._getframe(1).f_code.co_filename
    sys.stdout.write(f"{now} {back_file} line:{line} {leval}:{pstr}\n")
    sys.stdout.flush()

def walk(path):
    for root, _, names in os.walk(path):
        for name in names:
            abspath = os.path.join(root, name)
            relpath = os.path.relpath(abspath, path)
            yield relpath, abspath

def md5sum(filename):
    with open(filename, "rb") as fp:
        md5hash = hashlib.md5(fp.read())
    return md5hash.hexdigest()

def send_espace(content, receiver):
    data = {'content': content, 'receiver': receiver}
    requrl = 'http://cid-service.huawei.com/service-ldap/msg/espace'
    headers = {'Content-Type': 'application/json'}
    ret = requests.post(url=requrl, data=json.dumps(data), headers=headers)
    if not ret.ok:
        logging.error(ret.text)
    return ret.ok

def write_cfg(inifile, cfg):
    config = configparser.ConfigParser()
    config.read_dict(cfg)
    with open(inifile, "w", encoding="utf-8", newline="\n") as fp:
        config.write(fp)

def read_cfg(inifile):
    config = configparser.ConfigParser()
    with open(inifile, encoding="utf-8") as fp:
        config.read_file(fp)
    cfg = {}
    for section in config.sections():
        cfg[section] = {}
        for option in config.options(section):
            cfg[section][option] = config.get(section, option)
    return cfg


def is_linux():
    return True if platform.system() == "Linux" else False

def unmount_artifacts(mount_dir):
    getstatusoutput(["sudo", "umount", "-l", mount_dir], env={"LD_PRELOAD": ""})
    father = os.path.dirname(mount_dir)
    try:
        for sub in os.listdir(father):
            try:
                os.rmdir(os.path.join(father, sub))
            except Exception:
                pass
    except FileNotFoundError:
        pass


def mount_cmd(artifacts_dir, mount_dir):
    uname, pword = "pihertbbuint", "Hertint@2020"
    if ":/" in artifacts_dir:
        cmd = "sudo mount -t nfs -o nolock,vers=3,timeo=600,lookupcache=positive  %s %s" % (artifacts_dir, mount_dir)
    else:
        cmd = "sudo mount -t cifs %s %s -o username=\"%s\",password=\"%s\",cache=strict" % (artifacts_dir, mount_dir, uname, pword)
    logging.info(str(cmd)) #.replace(uname, '********').replace(pword, '********'))
    return cmd


def mount_artifacts(artifacts_dir, mount_dir):
    count = 5
    artifacts_dir = artifacts_dir.replace("\\", "/")
    while count > 0:
        unmount_artifacts(mount_dir)
        cmd = mount_cmd(artifacts_dir, mount_dir)
        os.makedirs(mount_dir, exist_ok=True)
        ret, txt = getstatusoutput(cmd, env={"LD_PRELOAD": ""})
        if "No such file or directory" in txt or "Not a directory" in txt or "mount.nfs: access denied" in txt \
            or "Network Error - 2" in txt:
            dirname = os.path.dirname(artifacts_dir)
            if dirname == artifacts_dir:
                return False
            if not mount_artifacts(dirname, mount_dir):
                return False
            os.makedirs(os.path.join(mount_dir, os.path.basename(artifacts_dir)), exist_ok=True)
            continue
        if ret != 0:
            logging.info(txt)
            count -= 1
            time.sleep(1)
            continue
        return True
    return False


class Mount():
    def __init__(self, src):
        self.src = src
        self.path = src
        self.__mount()

    def __mount(self):
        if not is_linux():
            return
        self.path = os.path.abspath(os.path.join("/usr1/mnt", str(time.time()).split(".")[-1]))
        if not mount_artifacts(self.src, self.path):
            raise Exception("mount error")

    def __del__(self):
        logging.debug(self.path)
        unmount_artifacts(self.path)


def makedir(path):
    try:
        os.makedirs(path)
    except:
        pass
    return os.path.isdir(path)

def mycopy(src, des):
    makedir(os.path.dirname(des))
    if os.path.isdir(src):
        for sub in os.listdir(src):
            if not mycopy(os.path.join(src, sub), os.path.join(des, sub)):
                return False
        return True
    try:
        shutil.copy(src, des)
        myprint("copy %s -> %s success" % (src, des))
        return True
    except Exception:
        myprint(traceback.format_exc())
        myprint("copy %s -> %s failed" % (src, des))
        return False
    finally:
        pass

def send_espace(content, receiver):
    if not receiver:
        return False
    logging.info(receiver)
    logging.info(content)
    data = {'content': content, 'receiver': receiver}
    requrl = 'http://cid-service.huawei.com/service-ldap/msg/espace'
    headers = {'Content-Type': 'application/json'}
    ret = requests.post(url=requrl, data=json.dumps(data), headers=headers)
    return ret.ok

class MyThread(threading.Thread):
    def __init__(self, func=None, *args, **kwargs):
        super().__init__()
        self._func = func if func else self.empty
        self.args = args
        self.kwargs = kwargs
        self.rslt = False
        self.depend_func = set()

    @staticmethod
    def empty():
        return True

    def depend(self, *func):
        for _func in func:
            self.depend_func.add(_func)

    def result(self):
        self.build()
        self.join()
        return self.rslt

    def build(self):
        for func in self.depend_func:
            func.build()
        try:
            self.start()
        except RuntimeError:
            pass

    def run(self):
        for func in self.depend_func:
            func.join()
            if not func.rslt:
                self.rslt = False
                return None
        self.rslt = self._func(*self.args, **self.kwargs)
        return None

if __name__ == '__main__':
    logging.info(123)